From 80dbec3f0e1e0724d710bc9c7d0294a80a2b75eb Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 10 Apr 2006 15:13:42 -0600 Subject: [PATCH] [IA64] get_pfn_list workaround As we know, the mechanism for hypervisor to pass parameter through pointer is not complete. Hypervisor use copy_from/to_user functions to copy parameter to hypervisor and copy result to user, if there is a tlb miss happening and hypervisor can't handled this. This hypercall fails, there is no mechanism to handle this failure, that may cause domain crash. Get_pfn_list hypercall copy large data from hypervisor to user, it is easy to trigger this issue when creating VTI-domain. If fails, Get_pfn_list returns the number of pfn entries, and this patch will Dummy access parameter memory block to cause this tlb mapping tracked by Hypervisor, then continue to do get_pfn_list. It's a workaround before we design a new mechanism of passing parameter thr pointer. Signed-off-by: Anthony Xu --- tools/libxc/xc_ia64_stubs.c | 67 ++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/tools/libxc/xc_ia64_stubs.c b/tools/libxc/xc_ia64_stubs.c index 1b35d9685f..d9372ae5a5 100644 --- a/tools/libxc/xc_ia64_stubs.c +++ b/tools/libxc/xc_ia64_stubs.c @@ -48,6 +48,12 @@ xc_plan9_build(int xc_handle, PERROR("xc_plan9_build not implemented\n"); return -1; } +/* + VMM uses put_user to copy pfn_list to guest buffer, this maybe fail, + VMM don't handle this now. + This method will touch guest buffer to make sure the buffer's mapping + is tracked by VMM, + */ int xc_ia64_get_pfn_list(int xc_handle, uint32_t domid, @@ -56,27 +62,48 @@ int xc_ia64_get_pfn_list(int xc_handle, unsigned int nr_pages) { dom0_op_t op; - int ret; - unsigned long max_pfns = ((unsigned long)start_page << 32) | nr_pages; - - op.cmd = DOM0_GETMEMLIST; - op.u.getmemlist.domain = (domid_t)domid; - op.u.getmemlist.max_pfns = max_pfns; - op.u.getmemlist.buffer = pfn_buf; - - if ( (max_pfns != -1UL) - && mlock(pfn_buf, nr_pages * sizeof(unsigned long)) != 0 ) - { - PERROR("Could not lock pfn list buffer"); - return -1; + int num_pfns,ret; + unsigned int __start_page, __nr_pages; + unsigned long max_pfns; + unsigned long *__pfn_buf; + __start_page = start_page; + __nr_pages = nr_pages; + __pfn_buf = pfn_buf; + + while(__nr_pages){ + max_pfns = ((unsigned long)__start_page << 32) | __nr_pages; + op.cmd = DOM0_GETMEMLIST; + op.u.getmemlist.domain = (domid_t)domid; + op.u.getmemlist.max_pfns = max_pfns; + op.u.getmemlist.buffer = __pfn_buf; + + if ( (max_pfns != -1UL) + && mlock(__pfn_buf, __nr_pages * sizeof(unsigned long)) != 0 ) + { + PERROR("Could not lock pfn list buffer"); + return -1; + } + + ret = do_dom0_op(xc_handle, &op); + + if (max_pfns != -1UL) + (void)munlock(__pfn_buf, __nr_pages * sizeof(unsigned long)); + + if (max_pfns == -1UL) + return 0; + + num_pfns = op.u.getmemlist.num_pfns; + __start_page += num_pfns; + __nr_pages -= num_pfns; + __pfn_buf += num_pfns; + + if (ret < 0) + // dummy write to make sure this tlb mapping is tracked by VMM + *__pfn_buf = 0; + else + return nr_pages; } - - ret = do_dom0_op(xc_handle, &op); - - if (max_pfns != -1UL) - (void)munlock(pfn_buf, nr_pages * sizeof(unsigned long)); - - return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; + return nr_pages; } long xc_get_max_pages(int xc_handle, uint32_t domid) -- 2.30.2